﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using SharpMap.Presentation.Wpf;
using SharpMap.Rendering.Rendering2D;

namespace SharpMap.Wpf
{
    public class GeoPanel : Canvas
    {
        //public static readonly DependencyProperty WpfViewTransformProperty =
        //    DependencyProperty.Register("WpfViewTransform",typeof(MatrixTransform),
        //    typeof(GeoPanel),
        //    new FrameworkPropertyMetadata(
        //        MatrixTransform.Identity
        //    , FrameworkPropertyMetadataOptions.Inherits
        //    | FrameworkPropertyMetadataOptions.AffectsArrange
        //    , WpfViewTransformPropertyChanged)
        //    );


        public static readonly DependencyProperty ToViewTransformProperty = MapControl.ToViewTransformProperty.AddOwner(typeof(GeoPanel)
      , new FrameworkPropertyMetadata(MatrixTransform.Identity
    , FrameworkPropertyMetadataOptions.Inherits
    | FrameworkPropertyMetadataOptions.AffectsArrange
    , WpfViewTransformPropertyChanged));



        public MatrixTransform ToViewTransform
        {
            get
            {
                return (MatrixTransform)GetValue(MapControl.ToViewTransformProperty);
            }
        }




        static void WpfViewTransformPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            GeoPanel This = target as GeoPanel;
        }



        public GeoPanel()
        {
            //Binding b = new Binding("WpfViewTransform");
            //b.Mode = BindingMode.OneWay;
            //b.Source = this;
            //SetBinding(RenderTransformProperty, b);
        }

        protected override void OnVisualParentChanged(DependencyObject oldParent)
        {
            base.OnVisualParentChanged(oldParent);
            DependencyObject depObj = this;
            while((depObj = VisualTreeHelper.GetParent(depObj)) != null)
            {
                MapControl mapControl = depObj as MapControl;
                if (mapControl != null)
                {
                    Binding b = new Binding("ToViewTransform");
                    b.Mode = BindingMode.OneWay;
                    b.Source = mapControl;
                    SetBinding(GeoPanel.ToViewTransformProperty, b);
                    break;
                }

            }


        }

        public static double GetWorldX(DependencyObject obj)
        {
            return (double)obj.GetValue(WorldXProperty);
        }

        public static void SetWorldX(DependencyObject obj, double value)
        {
            obj.SetValue(WorldXProperty, value);
        }


        public static readonly DependencyProperty WorldXProperty =
            DependencyProperty.RegisterAttached("WorldX", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, WorldXPropertyChanged));


        static void WorldXPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            
        }

        public static double GetWorldY(DependencyObject obj)
        {
            return (double)obj.GetValue(WorldYProperty);
        }

        public static void SetWorldY(DependencyObject obj, double value)
        {
            obj.SetValue(WorldYProperty, value);
        }

        public static readonly DependencyProperty WorldYProperty =
            DependencyProperty.RegisterAttached("WorldY", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, WorldYPropertyChanged));


        private static void SetWorldXInternal(DependencyObject obj, double value)
        {
            obj.SetValue(WorldXProperty, value);
        }

        private static void SetWorldYInternal(DependencyObject obj, double value)
        {
            obj.SetValue(WorldYProperty, value);
        }

        static void WorldYPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {

        }


        #region view coords
        public static double GetViewX(DependencyObject obj)
        {
            return (double)obj.GetValue(ViewXProperty);
        }

        public static void SetViewX(DependencyObject obj, double value)
        {
            obj.SetValue(ViewXProperty, value);

        }

        public static readonly DependencyProperty ViewXProperty =
            DependencyProperty.RegisterAttached("ViewX", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, ViewXPropertyChanged));


        static void ViewXPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {

        }

        public static double GetViewY(DependencyObject obj)
        {
            return (double)obj.GetValue(ViewYProperty);
        }

        public static void SetViewY(DependencyObject obj, double value)
        {
            obj.SetValue(ViewYProperty, value);

            
        }

        public static readonly DependencyProperty ViewYProperty =
            DependencyProperty.RegisterAttached("ViewY", typeof(double), typeof(GeoPanel),
            new FrameworkPropertyMetadata(double.NaN, ViewYPropertyChanged));


        private static void SetViewXInternal(DependencyObject obj, double value)
        {
            obj.SetValue(ViewXProperty, value);
            
        }

   
        private static void SetViewYInternal(DependencyObject obj, double value)
        {
            obj.SetValue(ViewYProperty, value);
        }


        static void ViewYPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {

        }
        #endregion





        void PlaceObject(DependencyObject target)
        {
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement e in InternalChildren)
            {
                e.Measure(availableSize);
            }

            return availableSize;
        }

        protected override Size ArrangeOverride(Size arrangeSize)
        {
            Rect finalRect = new Rect(0, 0, 0, 0);
             foreach (UIElement e in InternalChildren)
            {
                Rect r = new Rect(e.DesiredSize);
                Point location ;
                if (e.GetType() == typeof(ContentLayerItem))
                {
                    ContentControl cc = e as ContentControl;
                    location = ToViewTransform.Transform(new Point(GetWorldX(cc as UIElement), GetWorldY(cc as UIElement)));
                }
                else
                {
                    location = ToViewTransform.Transform(new Point(GetWorldX(e), GetWorldY(e)));
                }

                //move center to desired location, instead of upper left
                location.Offset(-e.DesiredSize.Width / 2.0, -e.DesiredSize.Height / 2.0);

                SetViewXInternal(e,location.X);
                SetViewYInternal(e,location.Y);

                
                r.Location = location;
                e.Arrange(r);
                finalRect.Union(r);
            }
            return arrangeSize;
        }

        Boolean _arranging = false;

    }
}
